package com.rizzo.analytics.services.repo;

import com.rizzo.analytics.domain.account.Account;
import com.rizzo.analytics.domain.account.Account_;
import com.rizzo.analytics.domain.trigger.Trigger_;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import javax.persistence.metamodel.ListAttribute;
import javax.persistence.metamodel.SingularAttribute;

public class TriggerSpecs<Trigger> extends EntitySpecs {

    @Override
    public Specification hasMoreChildrenThan(final long childCount) {
        throw new UnsupportedOperationException("Not applicable for class Trigger");
    }

    @Override
    public Specification hasChildrenWithProperty(final ListAttribute joinProperty, final SingularAttribute childProperty, final Object childPropertyValue) {
        throw new UnsupportedOperationException("Not applicable for class Trigger");
    }

    @Override
    public Specification fallsInPeriod(final DateTime startDate, final Period period) {
        return new Specification<Trigger>() {
            @Override
            public Predicate toPredicate(Root<Trigger> triggerRoot, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return fallsInPeriodPredicate(triggerRoot, criteriaQuery, criteriaBuilder, Trigger_.created, startDate, period);
            }
        };
    }

    @Override
    public Specification fallsInFuture() {
        return new Specification<Trigger>() {
            @Override
            public Predicate toPredicate(Root<Trigger> triggerRoot, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return fallsInFuturePredicate(triggerRoot, criteriaQuery, criteriaBuilder, Trigger_.created);
            }
        };
    }

    @Override
    public Specification fallsInPast() {
        return new Specification<Trigger>() {
            @Override
            public Predicate toPredicate(Root<Trigger> triggerRoot, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return fallsInPastPredicate(triggerRoot, criteriaQuery, criteriaBuilder, Trigger_.created);
            }
        };
    }

    public Specification hasAccountWithUsername(final String username) {
        return new Specification<Trigger>() {
            @Override
            public Predicate toPredicate(Root<Trigger> triggerRoot, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //select t from Trigger t left join t.account a where a.username = :username
                Join<Trigger, Account> join = triggerRoot.join((SingularAttribute<? super Trigger, Account>) Trigger_.account);
                return criteriaQuery.where(criteriaBuilder.equal(join.get(Account_.username), username)).getRestriction();
            }
        };
    }

}
